package laba1.task1;

import java.util.Arrays;

/**
 *
 * @author yakimovich
 */
public class Matrix {

    private double[][] array;

    /**
     * Constructs a Matrix with an empty array
     */
    public Matrix() {
        array = new double[0][0];
    }

    /**
     * Constructs a Matrix with the specified array
     *
     * @param array the specified array for created the Matrix
     * @throws IllegalArgumentException if size of the specified array is not correct
     */
    public Matrix(double[][] array) throws IllegalArgumentException{
        //A Matrix can be created only on the basis of a two-dimensional array   
        if (array.length != 2) {
            throw new IllegalArgumentException("Size of the array for a Matrix is not correct");
        }
        //fill in the blank cells of the Matrix with zeros
        if (array[0].length > array[1].length) {
            array[1] = Arrays.copyOf(array[1], array[0].length);
        } else {
            array[0] = Arrays.copyOf(array[0], array[1].length);
        }
        this.array = array;
    }

    /**
     * Returns the sum of Matrix with the specified Matrix
     *
     * @param summand Matrix to be summarize by this Matrix
     * @return sum of matrixes
     * @throws IllegalArgumentException if size of the summands is not correct
     */
    public Matrix sum(Matrix summand) throws IllegalArgumentException{
        //The Matrixes must have the same dimension
        if (this.getArray()[0].length != summand.getArray()[0].length) {
            throw new IllegalArgumentException("Size of the summands is not correct");
        }
        double[][] a = this.getArray();
        double[][] b = summand.getArray();
        double[][] result = new double[a.length][a[0].length];

        double sum = 0;
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[0].length; j++) {
                    sum = a[i][j] + b[i][j];
                result[i][j] = sum;
                sum = 0;
            }
        }
        return new Matrix(result);
    }

    /**
     * Returns the result of multiplying for this Matrix and specified Matrix
     *
     * @param factor Matrix to be multiplied by this Matrix
     * @return the result of multiplying for matrixes
     * @throws IllegalArgumentException if size of the factors is not correct
     */
    public Matrix mult(Matrix factor) throws IllegalArgumentException{
        //the number of columns of the first Matrix must be equal the number of rows of the second Matrix
        if (this.getArray()[0].length != factor.getArray().length) {
            throw new IllegalArgumentException("Size of the factors is not correct");
        }
        double[][] a = this.getArray();
        double[][] b = factor.getArray();
        double[][] result = new double[a.length][b[0].length];

        double sum = 0;
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b.length; j++) {
                for (int n = 0; n < a.length; n++) {
                    sum += a[i][n] * b[n][j];
                }
                result[i][j] = sum;
                sum = 0;
            }
        }
        return new Matrix(result);
    }

    /**
     * Returns the transpose of the Matrix
     *
     * @return the transpose of the Matrix
     */
    public Matrix transpose() {
        double[][] result = new double[getArray()[0].length][getArray().length];

        for (int i = 0; i < getArray()[0].length; i++) {
            for (int j = 0; j < getArray().length; j++) {
                result[i][j] = getArray()[j][i];
            }
        }
        return new Matrix(result);
    }

    /**
     * displays this Matrix on the screen
     */
    public void printMatrix() {
        String result = "";
        for (int i = 0; i < getArray().length; i++) {
            for (int j = 0; j < getArray()[0].length; j++) {
                System.out.printf("%.2f\t", getArray()[i][j]);
            }
            System.out.println();
        }
        System.out.println(result);
    }

    /**
     * @return the array
     */
    public double[][] getArray() {
        return array;
    }

    /**
     * @param array the array to set
     */
    public void setArray(double[][] array) {
        this.array = array;
    }
}